package com.aliyun.cloudcallcenter.crm.aliyun.controller;

import java.security.InvalidParameterException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import com.alibaba.fastjson.JSON;

import com.aliyun.cloudcallcenter.crm.aliyun.manager.UserManager;
import com.aliyun.cloudcallcenter.crm.aliyun.request.CreateUserRequest;
import com.aliyun.cloudcallcenter.crm.aliyun.request.SkillLevel;
import com.aliyun.cloudcallcenter.crm.aliyun.response.ListRolesResponse;
import com.aliyun.cloudcallcenter.crm.aliyun.response.ListRolesResponse.Role;
import com.aliyun.cloudcallcenter.crm.aliyun.response.ListSkillGroupsResponse;
import com.aliyun.cloudcallcenter.crm.aliyun.response.ListSkillGroupsResponse.SkillGroup;
import com.aliyun.cloudcallcenter.crm.model.User;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;

import com.aliyuncs.ccc.model.v20200701.CreateUserResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.ram.model.v20150501.CreateAccessKeyRequest;
import com.aliyuncs.ram.model.v20150501.CreateAccessKeyResponse;
import com.aliyuncs.ram.model.v20150501.CreateAccessKeyResponse.AccessKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * 云呼坐席操作
 */
@Controller
public class CccOpsController {

    private static final Logger logger = LoggerFactory.getLogger(CccOpsController.class);

    private static final String CCC_REGION = "cn-shanghai";
    private static final String CCC_PRODUCT = "CCC";
    private static final String CCC_ENDPOINT = "CCC";
    private static final String CCC_DOMAIN = "ccc.cn-shanghai.aliyuncs.com";
    private static final String CCC_VERSION = "2020-07-01";

    private static final String RAM_REGION = "cn-hangzhou";
    private static final String RAM_PRODUCT = "RAM";
    private static final String RAM_ENDPOINT = "RAM";
    private static final String RAM_DOMAIN = "ram.aliyuncs.com";

    private final Object locker = new Object();

    private DefaultAcsClient cccClient = null;

    private DefaultAcsClient ramClient = null;

    @Autowired
    private UserManager userManager;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Value("${aliyun.ccc.instanceId}")
    private String instanceId;

    @RequestMapping(value = "/ccc/register")
    public String getInstance(ModelMap model, Principal principal) throws ClientException {
        model.addAttribute("instanceId", instanceId);
        // 获取新增客服 CreateUser 所需的参数
        // ListRoles
        // TODO 此处采用CommonRequest的方式调用api
        CommonRequest listRolesRequest = new CommonRequest();
        listRolesRequest.setDomain(CCC_DOMAIN);
        listRolesRequest.setVersion(CCC_VERSION);
        listRolesRequest.setAction("ListRoles");
        listRolesRequest.putQueryParameter("InstanceId", instanceId);
        CommonResponse commonResponse = getCccClient(principal).getCommonResponse(listRolesRequest);
        ListRolesResponse listRolesResponse = JSON.parseObject(commonResponse.getData(), ListRolesResponse.class);
        List<Role> roleList = listRolesResponse.getData();
        model.addAttribute("roleList", roleList);
        // ListSkillGroups
        CommonRequest listSkillGroupsRequest = new CommonRequest();
        listSkillGroupsRequest.setDomain(CCC_DOMAIN);
        listSkillGroupsRequest.setVersion(CCC_VERSION);
        listSkillGroupsRequest.setAction("ListSkillGroups");
        listSkillGroupsRequest.putQueryParameter("InstanceId", instanceId);
        listSkillGroupsRequest.putQueryParameter("PageNumber", "1");
        listSkillGroupsRequest.putQueryParameter("PageSize", "20");
        commonResponse = getCccClient(principal).getCommonResponse(listSkillGroupsRequest);
        ListSkillGroupsResponse listSkillGroupsResponse = JSON.parseObject(commonResponse.getData(),
            ListSkillGroupsResponse.class);
        List<SkillGroup> skillGroupList = listSkillGroupsResponse.getData().getList();
        model.addAttribute("skillGroupList", skillGroupList);
        return "agentregister";
    }

    @RequestMapping(value = "/aliyun/ccc/createuser", method = RequestMethod.POST)
    public String createUser(ModelMap model, Principal principal, HttpServletRequest httpServletRequest,
        CreateUserRequest createUserRequest)
        throws ClientException {
        String loginName = createUserRequest.getLoginName();
        String displayName = createUserRequest.getDisplayName();
        String email = createUserRequest.getEmail();
        String roleId = createUserRequest.getRoleId();
        List<String> skillIdList = createUserRequest.getSkillIdList();

        // 调用云呼 CreateUser 创建客服
        // TODO 此处采用云呼的SDK调用api，注意云呼2.0 SDK version为 20200701
        com.aliyuncs.ccc.model.v20200701.CreateUserRequest createRequest = new com.aliyuncs.ccc.model
            .v20200701.CreateUserRequest();
        createRequest.setDisplayName(displayName);
        createRequest.setLoginName(loginName);
        createRequest.setEmail(email);
        createRequest.setInstanceId(instanceId);
        createRequest.setRoleId(roleId);
        createRequest.setWorkMode("ON_SITE");
        List<SkillLevel> skillLevelList = new ArrayList<>();
        // TODO 技能组等级目前传入固定值5
        skillIdList.forEach(
            id -> skillLevelList.add(new SkillLevel(id, 5))
        );
        createRequest.setSkillLevelList(JSON.toJSONString(skillLevelList));
        CreateUserResponse createUserResponse = getCccClient(principal).getAcsResponse(createRequest);

        // 调用 RAM CreateAccessKey 为用户创建访问密钥
        // 这里使用了 RAM SDK
        CreateAccessKeyRequest createAccessKeyRequest = new CreateAccessKeyRequest();
        createAccessKeyRequest.setUserName(loginName);
        CreateAccessKeyResponse createAccessKeyResponse = getRamClient(principal).getAcsResponse(createAccessKeyRequest);
        AccessKey accessKey = createAccessKeyResponse.getAccessKey();

        // 将新创建的坐席相关信息录入数据库
        User user = new User();
        user.setUserName(loginName);
        user.setAk(accessKey.getAccessKeyId());
        user.setSk(accessKey.getAccessKeySecret());
        // TODO 此处Demo用户缺省密码为 1234
        user.setPassword(bCryptPasswordEncoder.encode("1234"));
        userManager.addUser(user);

        // 获取用户列表
        List<User> userList = userManager.findAll();
        model.addAttribute("userList", userList);
        return "users";
    }

    @RequestMapping(value = "/workbench")
    public String login(Principal principal, ModelMap model) {
        String userName = principal.getName();
        User user = userManager.findByUserName(userName);
        model.addAttribute("loginName", user.getUserName());
        model.addAttribute("instanceId", instanceId);
        return "workbench";
    }

    private synchronized IAcsClient getCccClient(Principal principal) {
        if (cccClient == null) {
            synchronized (locker) {
                if (cccClient == null) {
                    String name = principal.getName();
                    User user = userManager.findByUserName(name);
                    cccClient = createCccClient(user.getAk(), user.getSk());
                }
            }
        }
        return cccClient;
    }

    private static DefaultAcsClient createCccClient(String accessKeyId, String secret) {
        try {
            DefaultProfile.addEndpoint(CCC_ENDPOINT, CCC_REGION, CCC_PRODUCT, CCC_DOMAIN);
        } catch (ClientException e) {
            logger.error(e.getMessage());
        }
        if (accessKeyId == null || secret == null) {
            throw new InvalidParameterException("ak, sk may not be null.");
        }
        IClientProfile profile = DefaultProfile.getProfile(CCC_REGION, accessKeyId, secret);
        return new DefaultAcsClient(profile);
    }

    private synchronized IAcsClient getRamClient(Principal principal) {
        if (ramClient == null) {
            synchronized (locker) {
                if (ramClient == null) {
                    String name = principal.getName();
                    User user = userManager.findByUserName(name);
                    ramClient = createRamClient(user.getAk(), user.getSk());
                }
            }
        }
        return ramClient;
    }

    private DefaultAcsClient createRamClient(String accessKeyId, String secret) {
        try {
            DefaultProfile.addEndpoint(RAM_ENDPOINT, RAM_REGION, RAM_PRODUCT, RAM_DOMAIN);
        } catch (ClientException e) {
            logger.error(e.getMessage());
        }
        if (accessKeyId == null || secret == null) {
            throw new InvalidParameterException("ak, sk may not be null.");
        }
        IClientProfile profile = DefaultProfile.getProfile(RAM_REGION, accessKeyId, secret);
        return new DefaultAcsClient(profile);
    }

}
